package com.pipayshop.service.impl;

import com.pipayshop.config.OrderQueueConfig;
import com.pipayshop.domain.StoreCommodityInfo;
import com.pipayshop.domain.StoreOrderInfo;
import com.pipayshop.domain.vo.*;
import com.pipayshop.mapper.PhysicalAccountInfoMapper;
import com.pipayshop.mapper.PhysicalStoreCommodityInfoMapper;
import com.pipayshop.mapper.PhysicalStoreOrderInfoMapper;
import com.pipayshop.service.PhysicalStoreOrderInfoService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pipayshop.exception.BusinessException;
import com.pipayshop.utils.Constants;
import com.pipayshop.utils.StringUtil;
import com.pipayshop.utils.TokenUtil;
import com.pipayshop.utils.ValidationUtil;
import io.jsonwebtoken.Claims;
import jakarta.annotation.Resource;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author wzx
 */
@Service
public class PhysicalStoreOrderInfoServiceImpl extends ServiceImpl<PhysicalStoreOrderInfoMapper, StoreOrderInfo> implements PhysicalStoreOrderInfoService {

    @Resource
    PhysicalStoreOrderInfoMapper shopOrderInfoMapper;

    @Resource
    @Qualifier("physicalAccountInfoMapper")
    PhysicalAccountInfoMapper physicalAccountInfoMapper;

    @Resource
    PhysicalStoreCommodityInfoMapper shopCommodityInfoMapper;

    @Resource
    private RabbitTemplate rabbitTemplate;

//    @Resource
//    private HotelCommodityLiveInfoMapper shopCommodityLiveInfoMapper;

    @Override
    @Cacheable(value = Constants.PHYSICAL_STORE_ORDER_LIST_KEY)
    public List<OrderListVO> getOrderList(GetOrderDataVO getOrderDataVO) {
        ValidationUtil.validateString(getOrderDataVO.getUserId(), "user_id_required");
        Long start = getOrderDataVO.getCurrentPage();
        Long size = getOrderDataVO.getPageSize();
        String userId = getOrderDataVO.getUserId();
        List<Integer> orderStatus = getOrderDataVO.getOrderStatus();
        if (start == null || start < 1) {
            start = 1L;
        }
        if (size == null || size < 1) {
            size = 10L;
        }

        start = (start - 1) * size;

        List<OrderListVO> orderList = shopOrderInfoMapper.getOrderList(userId, start, size, orderStatus);
        return orderList;
    }

    @Override
    public List<OrderListVO> getOrderListByShopName(GetOrderByNameVO getOrderByNameVO) {
        ValidationUtil.validateString(getOrderByNameVO.getUserId(), "user_id_required");
        ValidationUtil.validateString(getOrderByNameVO.getCommodityName(), "commodity_name_required");
        String userId = getOrderByNameVO.getUserId();
        String commodityName = getOrderByNameVO.getCommodityName();
        List<Integer> orderStatus = getOrderByNameVO.getOrderStatus();

        return shopOrderInfoMapper.getOrderListByShopName(userId, orderStatus, commodityName);
    }

    @Override
    @CacheEvict(value = Constants.PHYSICAL_STORE_ORDER_LIST_KEY, allEntries = true)
    public int delOrderByOrderId(String orderId) {
        if (orderId == null || "".equals(orderId)) {
            return 0;
        }
        return shopOrderInfoMapper.delete(new UpdateWrapper<StoreOrderInfo>()
                .eq("order_id", orderId));
    }

    @Override
    public StoreOrderDetailVO getOrderDetail(String orderId) {
        return shopOrderInfoMapper.getShopOrderDetailVO(orderId);
    }


    @Override
    @CacheEvict(value = Constants.PHYSICAL_STORE_ORDER_LIST_KEY, allEntries = true)
    public int completedOrder(String orderId) {
        return shopOrderInfoMapper.update(null, new UpdateWrapper<StoreOrderInfo>()
                .eq("order_id", orderId)
                .set("order_status", 2)
                .set("update_time", new Date()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = Constants.PHYSICAL_STORE_ORDER_LIST_KEY, allEntries = true)
    public int failOrder(String orderId) {
        StoreOrderInfo one = shopOrderInfoMapper.selectOne(new LambdaQueryWrapper<StoreOrderInfo>()
                .eq(StoreOrderInfo::getOrderId, orderId)
                .eq(StoreOrderInfo::getDelFlag, 0)
                .eq(StoreOrderInfo::getOrderStatus, 0));
        if (one == null) {
            return 0;
        }
        int i = shopCommodityInfoMapper.addStock(one.getNumber(), one.getCommodityId());
        int i1 = shopOrderInfoMapper.update(null, new UpdateWrapper<StoreOrderInfo>()
                .eq("order_id", orderId)
                .set("order_status", 3)
                .set("update_time", new Date()));
        if (i < 1 || i1 < 1) {
            throw new BusinessException("order_update_failed");
        }

        return 1;
    }


    @Override
    @CacheEvict(value = Constants.PHYSICAL_STORE_ORDER_LIST_KEY, allEntries = true)
    public void deleteFailOrders() {
        shopOrderInfoMapper.update(null, new UpdateWrapper<StoreOrderInfo>()
                .eq("order_status", 3)
                .set("del_flag", 1)
                .set("update_time", new Date()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = Constants.PHYSICAL_STORE_ORDER_LIST_KEY, allEntries = true)
    public String generateUnpaidOrder(String token) {
        // 解析令牌
        Claims dataFromToken = TokenUtil.getDataFromToken(token);
        BigDecimal transactionAmount = BigDecimal.valueOf(Double.parseDouble(dataFromToken.get("transactionAmount", String.class)));
        String commodityId = dataFromToken.get("commodityId", String.class);
        String uid = dataFromToken.get("uid", String.class);
        String shopId = dataFromToken.get("shopId", String.class);
        Integer number = dataFromToken.get("number", Integer.class);
        Date orderCreateTime = new Date();
        Date orderUpdateTime = new Date();
        // 生成orderId
        String orderId = StringUtil.generateShortId();
        StoreOrderInfo info = new StoreOrderInfo(orderId, transactionAmount, commodityId, uid, shopId, number, orderCreateTime, orderUpdateTime);
        //库存递减
        int reduce = shopCommodityInfoMapper.reduceStock(number, commodityId);
        int insert = shopOrderInfoMapper.insert(info);

        if (insert < 1 || reduce < 1) {
            String message = "generate_unpaid_order_failed";
            throw new BusinessException(message);
        }
        // 订单十分钟未支付的失效处理
        rabbitTemplate.convertAndSend(OrderQueueConfig.STORE_ORDER_EXCHANGE, "store", "store_" + orderId,
                message -> {
                    message.getMessageProperties().setExpiration("600000");
                    return message;
                });
        return orderId;
    }

    /**
     * 生成酒店未支付订单
     */
//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public String generateUnpaidLiveOrder(String token) {
//        // 解析令牌
//        Claims dataFromToken = TokenUtil.getDataFromToken(token);
//        BigDecimal transactionAmount = BigDecimal.valueOf(Double.parseDouble(dataFromToken.get("transactionAmount", String.class)));
//        String commodityId = dataFromToken.get("commodityId", String.class);
//        String uid = dataFromToken.get("uid", String.class);
//        String shopId = dataFromToken.get("shopId", String.class);
//        Integer number = dataFromToken.get("number", Integer.class);
//        // 生成orderId
//        String orderId = StringUtil.generateShortId();
//        StoreOrderInfo info = new StoreOrderInfo(orderId, transactionAmount, commodityId, uid, shopId, number);
//        //库存递减
//        int reduce = shopCommodityLiveInfoMapper.reduceLiveStock(number,commodityId);
//        int insert = shopOrderInfoMapper.insert(info);
//
//        if (insert < 1 || reduce < 1) {
//            String message = "generate_unpaid_order_failed";
//            throw new BusinessException(message);
//        }
//        // 订单十分钟未支付的失效处理
//        String pre = "shopLive_";
//        rabbitTemplate.convertAndSend(QueueConfig.QUEUE_MESSAGE_DELAY, pre+orderId, message1 -> {
//            message1.getMessageProperties().setExpiration(1000*60*10+"");
//            return message1;
//        });
//        return orderId;
//    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = Constants.PHYSICAL_STORE_ORDER_LIST_KEY, allEntries = true)
    public boolean payOrder(String token) {
        Claims dataFromToken = TokenUtil.getDataFromToken(token);
        String orderId = dataFromToken.get("orderId", String.class);
        String uid1 = dataFromToken.get("uid", String.class);
        BigDecimal transactionAmount = BigDecimal.valueOf(Double.parseDouble(dataFromToken.get("transactionAmount", String.class)));
        String commodityId = dataFromToken.get("commodityId", String.class);
        Integer number = dataFromToken.get("number", Integer.class);
        // 校验订单id是否已经存在，保证接口的幂等性，避免重复下单
        Long count = shopOrderInfoMapper.selectCount(new QueryWrapper<StoreOrderInfo>()
                .eq("order_id", orderId)
                .eq("order_status", 1));
        if (count != 0) {
            throw new BusinessException("order_already_paid！");
        }
        // 用户余额更新
        int uid = physicalAccountInfoMapper.updatePointBalanceByUid(transactionAmount, uid1);
        if (uid < 1) {
            throw new BusinessException("update_failed");
        }
        // 商品库存 、 月售量更新
        int update = shopCommodityInfoMapper.update(null, new UpdateWrapper<StoreCommodityInfo>()
                .eq("commodity_id", commodityId)
                .setSql("residue = residue - " + number)
                .setSql("monthly_sales = monthly_sales + " + number)
                .set("update_time", new Date()));
        if (update < 1) {
            throw new BusinessException("update_failed");
        }
        // 订单状态、修改时间更新
        int update1 = shopOrderInfoMapper.update(null, new UpdateWrapper<StoreOrderInfo>()
                .eq("order_id", orderId)
                .set("order_status", 1)
                .set("update_time", new Date()));
        if (update1 < 1) {
            throw new BusinessException("update_failed");
        }
        return true;
    }

//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public Map<String,String> payLiveOrder(String token) {
//        Claims dataFromToken = TokenUtil.getDataFromToken(token);
//        String orderId = dataFromToken.get("orderId", String.class);
//        String uid1 = dataFromToken.get("uid", String.class);
//        BigDecimal transactionAmount = BigDecimal.valueOf(Double.parseDouble(dataFromToken.get("transactionAmount", String.class)));
//        String commodityId = dataFromToken.get("commodityId", String.class);
//        Integer number = dataFromToken.get("number", Integer.class);
//
//        // 校验订单id是否已经存在，保证接口的幂等性，避免重复下单
//        Long count = shopOrderInfoMapper.selectCount(new QueryWrapper<StoreOrderInfo>()
//                .eq("order_id", orderId)
//                .eq("order_status", 1));
//        if (count != 0){throw new BusinessException("order_already_paid！");}
//        // 用户余额更新
//        int uid = physicalAccountInfoMapper.updatePointBalanceByUid(transactionAmount,uid1);
//        if (uid < 1){throw new RuntimeException();}
//        // 商品库存 、 月售量更新
//        int update = shopCommodityLiveInfoMapper.update(null, new UpdateWrapper<HotelCommodityLiveInfo>()
//                .eq("room_id", commodityId)
//                .setSql("inventory = inventory - " + number)
//                .setSql("monthly_sales = monthly_sales + " + number));
//        if (update < 1){throw new RuntimeException();}
//        // 订单状态、修改时间更新
//        int update1 = shopOrderInfoMapper.update(null, new UpdateWrapper<StoreOrderInfo>()
//                .eq("order_id", orderId)
//                .set("order_status", 1)
//                .set("update_time", new Date()));
//        if (update1 < 1){throw new RuntimeException();}
//        //添加交易记录
//        Map<String,String> map = new HashMap<>();
//        map.put("flag","true");
//        map.put("order_id",orderId);
//        return map;
//    }

    @Override
    public PageDataVO getOrderListByShopId(GetOrderDataVO getOrderDataVO) {
        getOrderDataVO.setCurrentPage((getOrderDataVO.getCurrentPage() - 1) * getOrderDataVO.getPageSize());
        List<OrderListVO> voList = shopOrderInfoMapper.getOrderListByShopId(getOrderDataVO);
        Integer count = shopOrderInfoMapper.getOrderListCountByShopId(getOrderDataVO);
        return new PageDataVO(count, voList);
    }

    /**
     * 未支付订单改价接口
     */
    @Override
    @CacheEvict(value = Constants.PHYSICAL_STORE_ORDER_LIST_KEY, allEntries = true)
    public int changePrice(String token) {
        Claims dataFromToken = TokenUtil.getDataFromToken(token);
        String orderId = dataFromToken.get("orderId", String.class);
        BigDecimal price = BigDecimal.valueOf(Double.parseDouble(dataFromToken.get("price", String.class)));
        if (price.doubleValue() < 0) {
            throw new BusinessException("invalid_amount");
        }
        return shopOrderInfoMapper.update(null, new LambdaUpdateWrapper<StoreOrderInfo>()
                .eq(StoreOrderInfo::getOrderId, orderId)
                .eq(StoreOrderInfo::getOrderStatus, 0)
                .eq(StoreOrderInfo::getDelFlag, 0)
                .set(StoreOrderInfo::getTransactionAmount, price));
    }


}
